import { acceptHMRUpdate, defineStore } from 'pinia'
import { reactive, ref } from 'vue'
import { throttle } from "/@/assets/js/utils"
export const reportBuryinigPointStrore = defineStore('reportBuryingPointObj', () => {
    // 定义一个接口来描述数组中的对象  
    interface Item {
        name: string;
        value: number;
        label: string; // 注意：这里可能是个拼写错误，通常应该是 'label'  
        range: any[]; // 或者你可以指定一个更具体的类型，比如 number[]、string[] 等  
    }


    const reportType = ref("1")  //报告类型
    const isDetailVersion = ref(false) //判断是不是详情页的滚动

    //区域模块 一级模块
    const moduleEventArray: Item[] = reactive(
        [
            { name: '基本信息', value: 0, label: 'BasedPerson', range: [] },
            { name: '保单梳理', value: 0, label: 'policySorting', range: [] },
            { name: '保障责任解读', value: 0, label: 'responsibility', range: [] },
            { name: '费用筹划', value: 0, label: 'costPlanning', range: [] },
            { name: '未来年度缴费水平', value: 0, label: 'futureAnnualPaymentLevel', range: [] },
            { name: '其他客户权益', value: 0, label: 'otherCustomerRights', range: [] },
        ]
    );

    // 模块内部的二级事件
    const moduleEventLeavelTwoArray: Item[] = reactive([
        { name: '保单梳理-分布汇总', value: 0, label: 'policySortingSummary', range: [] },
        { name: '保单梳理-被保人', value: 0, label: 'policySortingInsured', range: [] },
        // {name:'保单梳理-投保人',value:0,label:'policySortingPolicyholder',range:[]},  该模块暂时考虑和被保人模块的高度获取更新为一个模块 通过标识区分模块
        { name: '保障责任解读-可解读条款列表', value: 0, label: 'responsibilityInterpretable', range: [] },
        { name: '保障责任解读-保障责任一览', value: 0, label: 'responsibilityOverview', range: [] },
        { name: '保障责任解读-保障责任分布情况', value: 0, label: 'responsibilityDistribution', range: [] },
        { name: '其他客户权益-价值解读', value: 0, label: 'otherCustomerRightsEquity', range: [] },
        { name: '其他客户权益-保单受益人列表', value: 0, label: 'otherCustomerRightsBeneficiary', range: [] },
        { name: '其他客户权益-理赔指引', value: 0, label: 'otherCustomerRightsGlaimasGuidelines', range: [] },
    ])


    //区分二级模块的保单梳理被保人还是投保人   0-》被保人 1=》投保人 
    const distinguishInsuredAndPolicyholder = ref(0)


    // 定义一个接口来描述数组中的对象  
    interface BulletEvent {
        name: string;
        value: number;
        label: string; // 注意：这里可能是个拼写错误，通常应该是 'label'  
    }


    // 弹窗对应的事件   三级模块事件
    const BulletEventArray: BulletEvent[] = reactive([
        { name: '温馨提示', value: 0, label: 'warmTips' }, //特殊的一级模块，但是属于弹窗，所以放进来特殊处理
        { name: '可解读条款列表弹窗', value: 1, label: 'interpretablePopWindow' },
        { name: '身故责任', value: 2, label: 'guaranteeLiabilityAccidents' },
        { name: '全残/高残责任', value: 3, label: 'ensuringFullDisabilityRespon' },
        { name: '伤残责任', value: 4, label: 'protectionResponDisability' },
        { name: '疾病责任', value: 5, label: 'guaranteeResponDisseeases' },
        { name: '医疗责任', value: 6, label: 'ensuringResponMedical' },
        { name: '生存金责任', value: 7, label: 'guaranteeResponSurvivalFund' },
        { name: '其他责任', value: 8, label: 'otherResponProtection' },
    ])


    // 将获取失败的数据 设置定时器  稍后获取
    let acquisitionFailedArray = ref([])
    // 设置的标准线 所在的高度
    const virtualLineTop = ref(0)
    // 获取页面垂直滚动的偏移量  其实就是页面卷上去的高度   需要在想下详情页进行设置
    const scrollTop = ref(0)

    //获取元素高度(获取元素高度，将获取的高度呢绒放到埋点数组中，方便日后处理)
    const getElementHeight = (el: any, label: string, leavel: number) => {
        if (leavel == 1) {
            //一级模块获取高度
            try {
                //设置标准线的高度
                if (label == 'virtualLine') {
                    const rect = el?.value.getBoundingClientRect();
                    virtualLineTop.value = parseInt(rect.top)
                }
                // 获取元素相对于视口的矩形信息  
                const rect = el?.value.getBoundingClientRect();
                const elementTop = rect.top + scrollTop.value;
                setValueByLabel(label, parseInt(el?.value.getBoundingClientRect().height), parseInt(elementTop))
            } catch (e: any) {
                // console.log(e, "未获取到元素的高度")
            }
        } else {
            // 预计二级模块会用到该方法，因为二级模块存在间隔
            try {
                // 获取元素相对于视口的矩形信息  
                const rect = el?.value.getBoundingClientRect();
                // 计算元素相对于文档的顶部距离  
                const elementTop = rect.top + scrollTop.value;
                setValueByTwoLabelLevel(label, parseInt(el?.value.getBoundingClientRect().height), parseInt(elementTop))
            } catch {
                let obj = {
                    name: el,
                    la: label,
                    lev: leavel,
                }
                acquisitionFailedArray.value.push(obj)
            }
        }
        if (acquisitionFailedArray.value.length != 0) {
            setTimeout(() => {
                reverseGetElHight()
            }, 5000)
        }
    }


    //重新获取高度  (当页面初始化的时候没有获取到高度的时候，二次获取高度)
    const reverseGetElHight = () => {
        if (acquisitionFailedArray.value.length) {
            acquisitionFailedArray.value.forEach(item => {
                getElementHeight(item.name, item.la, item.lev)
            })
        }
        // 重新获取后记得清空需要重新获取元素的数组
        acquisitionFailedArray.value = []
    }

    // 发送事件   主要针对 弹窗事件   即一级事件 
    const sendEvent = (moduleName: string) => {
        console.log("一级模块名称=>", moduleName);
    }


    //特殊的切换事件   主要针对二级事件
    const specialSwitchEvent = (name: string) => {
        //特殊的切换事件，主要页面操作过程中引起了页面高度变化，并且需要调用发送埋点请求的事件
        console.log("二级模块名称", name);
    }


    // 发送事件   主要针对 特殊的弹窗一级模块名称(温馨提示，虽然是弹窗事件，但是属于一级)
    const sendOneEvent = (moduleName: string) => {
        console.log("特殊的弹窗一级模块名称=>", findNameByValue(moduleName));
    }
    
    //三级模块事件的开关   (用于滚动事件的控制，当三级弹窗开启的时候，页面内容发生滚动，页面会监听一二级事件的发送，所以设置开关，当三级弹窗开启时，内容区域的滚动不开启一二级事件的发送)
    const thirdLevelSwitch = ref(false)
    
    // 发送事件   主要针对 弹窗事件   即三级事件 
    const sendThreeEvent = (moduleName: string) => {
        thirdLevelSwitch.value = true
        console.log("三级模块名称=>", findNameByValue(moduleName));
    }


    //特殊关闭弹窗(三级模块）埋点事件  目前调用对应模块的二级埋点事件
    const specialColsePop = (name: string) => {
        thirdLevelSwitch.value = false
        //当三级关闭的时候  开启页面的滚动监听
        //特殊的切换事件，主要页面操作过程中引起了页面高度变化，并且需要调用发送埋点请求的事件
        console.log("发现特殊的弹窗关闭事件要找二级", name);
    }


    // 查找函数 (通过value找name) 
    const findNameByValue = (name: string) => {
        let obj = {}
        BulletEventArray.forEach(item => {
            if (item.name == name) {
                obj = item
            }
        })
        return obj
    }


    // 查找函数  一级模块 将获取的高度，设置到一级模块对象上
    const setValueByLabel = (label: string, height: number, rangeBegin: number): any => {
        const item = moduleEventArray.find(item => item.label === label);
        if (item) {
            setTimeout(()=>{
                item.value = height
                item.range = []
                item.range = [rangeBegin, rangeBegin + height]
            },100)
        } 
    }


    // 查找函数  二级模块   将获取的高度，设置到二级模块对象上
    const setValueByTwoLabelLevel = (label: string, height: number, rangeBegin: number): any => {
        const item = moduleEventLeavelTwoArray.find(item => item.label === label);
        if (item) {
            setTimeout(()=>{
                item.value = height
                item.range = []
                item.range = [rangeBegin, rangeBegin + height]
            },100)
        } 
    }


    // 获取滚动事件(当屏幕滚动时，关注一级和二级模块的滚动时间)
    const handleScrollEvent = (Number: number) => {
        // 因为别的页面存在滚动事件，导致其他页面在发生滚送时，引起该事件的调用
        // 特设置阀门进行控制
        if(isDetailVersion.value){
            // 一级因为是连续的模块，所以处理方案为，将模块的高度累计，处理高度数据为一个递增的数组，当前滚动高度在那个范围算那个模块
            // (一级模块   后发现因为模块中间存在空白，所以默认为非连续模块  所以设置range属性，判断当前滚动高度是否在range范围内，如果在触发对应的一级事件，否则不触发）
            // 二级模块因为非连续行，所以二级模块源数据存在range属性，判断当前滚动高度是否在range范围内，如果在触发二级事件，否则不触发
            // 二级需要特殊关注：部分属性时切换展示，所以考虑是否根据当前table所在进行切换管理
            //当不是三级弹窗的滚动时，才会关注滚动事件
            if(!thirdLevelSwitch.value){
                getPrimaryModule(Number)
            }
        }
    }


    // 使用节流函数包装 handleScroll  
    // const throttledHandleScroll = throttle(handleScrollEvent, 2000);
    const throttledHandleScroll = throttle(handleScrollEvent, 200);



    const currentLeavel = ref("")
    const preOneLeavel = ref("")   //一级模块保存的之前的模块名称，用于判断滚动事件是否发行模块更换
    const currentTwoLeavel = ref("")
    const preTwoLeavel = ref("") //二级模块保存的之前的模块名称，用于判断滚动事件是否发行模块更换
    
    //获取到一级的那个模块
    const getPrimaryModule = (position: number) => {
        let reallPosition = position + virtualLineTop.value
        currentLeavel.value = getNameByPosition(moduleEventArray, reallPosition)
        //这里可以继续获取二级模块的内容
        currentTwoLeavel.value = getNameByPosition(moduleEventLeavelTwoArray, reallPosition)
        //这里需要判断 用户是不是在同一个模块中进行滚动，如果是一个模块中不需要发送埋点请求
        if(currentLeavel.value != preOneLeavel.value && currentLeavel.value != ''){
            //一级模块发生改变   发送一级模块埋点事件
            sendEvent(currentLeavel.value)
        }
        if(currentTwoLeavel.value != preTwoLeavel.value && currentTwoLeavel.value !=""){
            //二级模块发生改变   发送二级模块埋点事件
            specialSwitchEvent(currentTwoLeavel.value)
        }
        //在每一次滚动事件的最后给一二级的老数据进行赋值
        preOneLeavel.value = currentLeavel.value
        preTwoLeavel.value = currentTwoLeavel.value
    }


    interface ArrayType {
        name: string,
        value: number,
        range: [],
        label: string
    }

    const getNameByPosition = (myarray: Array<Item>, position: number) => {
        let reallyName = ""
        myarray.forEach(item => {
            if (item.range[0] < position && position < item.range[1]) {
                reallyName = item.name
            }
        })
        return reallyName
    }


    //重置store中的部分数据
    const resetMyStoreData = ()=>{
        scrollTop.value = 0
        currentLeavel.value = ""
        preOneLeavel.value = ""
        currentTwoLeavel.value = ""
        preTwoLeavel.value = ""
    }


    return { isDetailVersion,reportType, scrollTop, moduleEventArray, moduleEventLeavelTwoArray, BulletEventArray, distinguishInsuredAndPolicyholder,currentLeavel,preOneLeavel, getElementHeight, sendThreeEvent,sendOneEvent, handleScrollEvent, throttledHandleScroll, specialSwitchEvent, specialColsePop,resetMyStoreData }
}, {
    persist: true
})

if (import.meta.hot) {
    import.meta.hot.accept(acceptHMRUpdate(reportBuryinigPointStrore, import.meta.hot))
}  
